#include "coexistence_matrix.h"
#include "stdio.h"

CoexistenceMatrix::CoexistenceMatrix(int max_objects_detectable) {

  this->max_objects_detectable = max_objects_detectable;
  coexistence_matrix = new int*[max_objects_detectable];
  for (int i = 0; i < max_objects_detectable; ++i) {
    coexistence_matrix[i] = new int[max_objects_detectable];
  }

  for (int i = 0; i < max_objects_detectable; ++i) {
    for (int j = 0; j < max_objects_detectable; ++j) {
      coexistence_matrix[i][j] = 0;
    }
  }

  max_object_label = 0;
}

void CoexistenceMatrix::ResetDataStructures() {

  for (int i = 0; i < max_object_label; ++i) {
    for (int j = 0; j < max_object_label; ++j) {
      coexistence_matrix[i][j] = 0;
    }
  }
  max_object_label = 0;
}

CoexistenceMatrix::~CoexistenceMatrix() {

  for (int i = 0; i < max_objects_detectable; ++i) {
    delete [] coexistence_matrix[i];
  }
  delete [] coexistence_matrix;
}

void CoexistenceMatrix::MinimizeLabelsBetweenRows() {

  for (int i = 1; i <= max_object_label; i++) {
    int minimum = 2147483647; //valor maximo para variavel int

    for (int j = 1; j <= max_object_label; j++) {
      int *pointer;
      pointer = &coexistence_matrix[i][j];
      if (*pointer != 0 && *pointer < minimum)
        minimum = *pointer;
    }

    if (minimum != 2147483647) {
      for (int j = 1; j <= max_object_label; j++) {
        int *pointer;
        pointer = &coexistence_matrix[i][j];
        if (*pointer != 0)
          *pointer = minimum;
      }
    }
  }
}

void CoexistenceMatrix::MinimizeLabelsBetweenColumns() {

  for (int j = 1; j <= max_object_label; j++) {
    int minimum = 2147483647;
    for (int i = 1; i <= max_object_label; i++) {
      int *pointer;
      pointer = &coexistence_matrix[i][j];
      if (*pointer != 0 && *pointer < minimum)
        minimum = *pointer;
    }

    if (minimum != 2147483647) {
      for (int i = 1; i <= max_object_label; i++) {
        int *pointer;
        pointer = &coexistence_matrix[i][j];
        if (*pointer != 0)
          *pointer = minimum;
      }
    }
  }
}

void CoexistenceMatrix::Fill(int label, int coexistent_label) {

  coexistence_matrix[label][coexistent_label] = label;
  coexistence_matrix[coexistent_label][label] = label;
  if (label > max_object_label)
    max_object_label = label;
}

void CoexistenceMatrix::MinimizeLabels() {

  for (int i = 1; i <= max_object_label; ++i) {
    coexistence_matrix[i][i] = i;
  }

  MinimizeLabelsBetweenRows();
  MinimizeLabelsBetweenColumns();
  MinimizeLabelsBetweenRows();

  for (int i = 1; i <= max_object_label; ++i) {
    int *current_cell = &coexistence_matrix[i][i];
    int current_cell_value = *current_cell;

    *current_cell = coexistence_matrix[current_cell_value][current_cell_value];
  }
  /*
  printf("   ");
  for (int i = 1; i <= max_object_label; ++i) {
    printf("%3d ", i);
  }
  printf("\n");
  for (int i = 1; i <= max_object_label; ++i) {
    printf("%3d", i);
    for (int j = 1; j <= max_object_label; ++j) {
      printf("%3d ", coexistence_matrix[i][j]);
    }
    printf("\n");
  }
   */
}

int CoexistenceMatrix::GetCorrectLabel(int label) {

  return coexistence_matrix[label][label];
}
